package com.example.springbootdockertest.config;

import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.ScheduledUpdateCertificatesVerifier;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.impl.client.CloseableHttpClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.io.FileInputStream;
import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;

/**
 * 微信支付请求配置
 *
 * @Author liguangcheng
 * @Date 2021/12/8 9:34 上午
 * @Vision 1.0
 **/
@Configuration
// @PropertySource("classpath:application.properties") //读取配置文件
// @ConfigurationProperties(prefix = "wxpay") //读取wxpay节点
@Getter
@Setter
@Slf4j
public class WxPayConfig {

    // 商户号
    @Value("${wxpay.mch-id}")
    private String mchId;

    // 商户API证书序列号
    @Value("${wxpay.mch-serial-no}")
    private String mchSerialNo;

    // 商户私钥文件
    @Value("${wxpay.private-key-path}")
    private String privateKeyPath;

    // APIv3密钥
    @Value("${wxpay.api-v3-key}")
    private String apiV3Key;

    // APPID
    @Value("${wxpay.appid}")
    private String appid;

    // 微信服务器地址
    @Value("${wxpay.domain}")
    private String domain;

    // 接收结果通知地址
    @Value("${wxpay.notify-domain}")
    private String notifyDomain;

    // secret
    private String secret = "e9ae9d2da8d62df8b0e02e540fd99d8c";
    // templateId
    private String templateId = "XlcyLaGoNMDCtUQJx1YeCcJ07wwcHi0h0Gw4Fr3HKE8";
    // accessTokenUrl
    private String accessTokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={}&secret={}";
    // messageUrl
    private String messageUrl = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=";
    // openidUrl
    private String openidUrl = "https://api.weixin.qq.com/sns/jscode2session";


    /**
     * 获取商户的私钥文件
     *
     * @param filename
     * @return
     */
    private PrivateKey getPrivateKey(String filename) {

        try {
            log.info("filename==>{}", filename);
            FileInputStream inputStream = new FileInputStream(filename);
            return PemUtil.loadPrivateKey(inputStream);
        } catch (Exception e) {
            log.error("私钥文件不存在");
            throw new RuntimeException("私钥文件不存在", e);
        }
    }

    /**
     * 获取签名验证器
     *
     * @return
     */
    @Bean
    public ScheduledUpdateCertificatesVerifier getVerifier() {

        log.info("获取签名验证器");

        //获取商户私钥
        PrivateKey privateKey = getPrivateKey(privateKeyPath);

        //私钥签名对象
        PrivateKeySigner privateKeySigner = new PrivateKeySigner(mchSerialNo, privateKey);

        //身份认证对象
        WechatPay2Credentials wechatPay2Credentials = new WechatPay2Credentials(mchId, privateKeySigner);

        // 使用定时更新的签名验证器，不需要传入证书
        ScheduledUpdateCertificatesVerifier verifier = new ScheduledUpdateCertificatesVerifier(
                wechatPay2Credentials,
                apiV3Key.getBytes(StandardCharsets.UTF_8));

        return verifier;
    }


    /**
     * 获取http请求对象
     *
     * @param verifier
     * @return
     */
    @Bean(name = "wxPayClient")
    public CloseableHttpClient getWxPayClient(ScheduledUpdateCertificatesVerifier verifier) {

        log.info("获取httpClient");

        //获取商户私钥
        PrivateKey privateKey = getPrivateKey(privateKeyPath);

        WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
                .withMerchant(mchId, mchSerialNo, privateKey)
                .withValidator(new WechatPay2Validator(verifier));
        // ... 接下来，你仍然可以通过builder设置各种参数，来配置你的HttpClient

        // 通过WechatPayHttpClientBuilder构造的HttpClient，会自动的处理签名和验签，并进行证书自动更新
        CloseableHttpClient httpClient = builder.build();

        return httpClient;
    }

    /**
     * 获取HttpClient，无需进行应答签名验证，跳过验签的流程
     */
    @Bean(name = "wxPayNoSignClient")
    public CloseableHttpClient getWxPayNoSignClient() {

        //获取商户私钥
        PrivateKey privateKey = getPrivateKey(privateKeyPath);

        //用于构造HttpClient
        WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
                //设置商户信息
                .withMerchant(mchId, mchSerialNo, privateKey)
                //无需进行签名验证、通过withValidator((response) -> true)实现
                .withValidator((response) -> true);

        // 通过WechatPayHttpClientBuilder构造的HttpClient，会自动的处理签名和验签，并进行证书自动更新
        CloseableHttpClient httpClient = builder.build();

        log.info("== getWxPayNoSignClient END ==");

        return httpClient;
    }

}


